package com.qianya.oa.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qianya.oa.common.core.domain.entity.SysUser;
import com.qianya.oa.common.utils.StringUtils;
import com.qianya.oa.domain.FormInst;
import com.qianya.oa.domain.FormInstData;
import com.qianya.oa.dto.FormSubmitParam;
import com.qianya.oa.mapper.FormInstDataMapper;
import com.qianya.oa.mapper.FormInstMapper;
import com.qianya.oa.service.FormInstService;
import com.qianya.oa.service.SysUserService;
import com.qianya.oa.service.SysUserMessageService;
import com.qianya.oa.vo.FormVo;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service
public class FormInstServiceImpl implements FormInstService {

    @Resource
    private FormInstMapper formInstMapper;

    @Resource
    private TaskService taskService;

    @Resource
    private IdentityService identityService;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private FormInstDataMapper formInstDataMapper;

    @Resource
    private SysUserService sysUserService;

    @Override
    public FormVo get(String processInstanceId, String formKey) {
        FormVo formVo = new FormVo();
        FormInst formInstData = formInstMapper.selectByProcInstIdAndFormKey(processInstanceId, formKey);
        formVo.setFormData(formInstData.getFormData());
        return formVo;
    }

    /**
     * 存储表单实例数据
     *
     * @param processInstanceId
     * @param formData          表单实例名称、数据 键值对
     * @return
     */
    private boolean saveFormData(String processInstanceId, String formKey, String formData) {
        Date now = new Date();
        FormInst formInst = new FormInst();
        formInst.setFormData(formData);
        formInst.setCreateTime(now);
        formInst.setUpdateTime(now);
        formInst.setProcInstId(processInstanceId);
        formInst.setFormKey(formKey);
        int i = formInstMapper.insertSelective(formInst);

        if (i > 0) {
            //存储拆分后的表单实例数据
            ArrayList<FormInstData> formInstDataList = new ArrayList<>();
            Object parsedObj = JSONObject.parse(formData);
            splitFormData(formInstDataList, formKey, "", parsedObj, processInstanceId, formKey);
            if (formInstDataList.size() > 0) {
                int i1 = formInstDataMapper.batchInsert(formInstDataList);
                return i1 > 0;
            }
        }
        return false;
    }

    /**
     * 拆分表单实例数据
     *
     * @param formInstDataList
     * @param parentField
     * @param parentFieldName
     * @param jsonStr
     */
    private void splitFormData(ArrayList<FormInstData> formInstDataList, String parentField, String parentFieldName, Object jsonStr, String processInstanceId, String formKey) {
        Date now = new Date();
        if (jsonStr instanceof JSONObject) {
            JSONObject jsonObject = (JSONObject) jsonStr;
            Set<Map.Entry<String, Object>> entries = jsonObject.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                String fieldName1 = entry.getKey();
                Object fieldValue = entry.getValue();
                if (fieldValue instanceof JSONObject || fieldValue instanceof JSONArray) {
                    splitFormData(formInstDataList, parentField, fieldName1, fieldValue, processInstanceId, formKey);
                } else {
                    FormInstData formInstData = new FormInstData();
                    formInstData.setFieldPath(parentField + "." + fieldName1);
                    formInstData.setFieldName(fieldName1);
                    formInstData.setFieldType(fieldValue.getClass().getName());
                    formInstData.setFieldValue(fieldValue.toString());
                    formInstData.setProcInstId(processInstanceId);
                    formInstData.setFormKey(formKey);
                    formInstData.setCreateTime(now);
                    formInstData.setUpdateTime(now);
                    formInstData.setVersion(1);
                    formInstDataList.add(formInstData);
                }
            }
        } else if (jsonStr instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) jsonStr;
            for (int i = 0; i < jsonArray.size(); i++) {
                String parent = parentField;
                Object fieldValue = jsonArray.get(i);
                if (fieldValue instanceof JSONObject || fieldValue instanceof JSONArray) {
                    if (StringUtils.isNotEmpty(parentFieldName)) {
                        if (StringUtils.isNotEmpty(parentField)) {
                            parent = parentField + "." + parentFieldName + "[" + i + "]";
                        } else {
                            parent = parentFieldName + "[" + i + "]";
                        }
                    } else if (StringUtils.isNotEmpty(parentField)) {
                        parent = parentField + "[" + i + "]";
                    }
                    splitFormData(formInstDataList, parent, parentFieldName, fieldValue, processInstanceId, formKey);
                } else {
                    FormInstData formInstData = new FormInstData();
                    formInstData.setFieldPath(parentField + "." + parentFieldName);
                    formInstData.setFieldName(parentFieldName);
                    formInstData.setFieldType(fieldValue.getClass().getName());
                    formInstData.setFieldValue(fieldValue.toString());
                    formInstData.setProcInstId(processInstanceId);
                    formInstData.setFormKey(formKey);
                    formInstData.setCreateTime(now);
                    formInstData.setUpdateTime(now);
                    formInstData.setVersion(1);
                    formInstDataList.add(formInstData);
                }
            }
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String submit(SysUser user, FormSubmitParam formSubmitParam) {
        String formKey = formSubmitParam.getFormKey();
        String processDefinitionKey = formSubmitParam.getProcessDefinitionKey();
        String formData = formSubmitParam.getFormData();
        String username = user.getLoginName();
        long l = System.currentTimeMillis();
        //第一个节点，创建任务，发起流程
        identityService.setAuthenticatedUserId(username);
        Map<String, Object> variables = new HashMap<>();
        variables.put("applicantId", user.getUserId());
        variables.put("applicant", user.getLoginName());
        //放入职位以及人员列表
        variables.putAll(sysUserService.selectAllPostUserName());

        String businessKey = processDefinitionKey + l;
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
        // 自动完成第一个任务
        Task autoTask = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).processInstanceBusinessKey(businessKey).singleResult();
        autoTask.setAssignee(username);
        String taskId = autoTask.getId();
        String processInstanceId = autoTask.getProcessInstanceId();
        saveFormData(processInstanceId, formKey, formData);
        taskService.complete(taskId);
        return null;
    }



    @Override
    public int deleteByPrimaryKey(Long id) {
        return formInstMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(FormInst record) {
        return formInstMapper.insert(record);
    }

    @Override
    public int insertOrUpdate(FormInst record) {
        return formInstMapper.insertOrUpdate(record);
    }

    @Override
    public int insertOrUpdateSelective(FormInst record) {
        return formInstMapper.insertOrUpdateSelective(record);
    }

    @Override
    public int insertSelective(FormInst record) {
        return formInstMapper.insertSelective(record);
    }

    @Override
    public FormInst selectByPrimaryKey(Long id) {
        return formInstMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(FormInst record) {
        return formInstMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(FormInst record) {
        return formInstMapper.updateByPrimaryKey(record);
    }

    @Override
    public int updateBatch(List<FormInst> list) {
        return formInstMapper.updateBatch(list);
    }

    @Override
    public int batchInsert(List<FormInst> list) {
        return formInstMapper.batchInsert(list);
    }

}


